import datetime
import time
from collections import OrderedDict
from datetime import timedelta

from django.db.models import Sum, Count
from django.http import JsonResponse
from django.shortcuts import render

from web import models


def get_data_dict(model_list, name, field):
    today = datetime.datetime.now().date() + timedelta(days=1)
    date_dict = OrderedDict()

    if len(model_list) > 1:
        if name == '攻击合计':
            for i in range(0, 30):
                date = today - timedelta(days=i)
                date_dict[date.strftime("%Y-%m-%d")] = [time.mktime(date.timetuple()) * 1000, 0]
            for model in model_list:
                queryset = model.objects.filter(create_datetime__gt=today - timedelta(days=29)).extra(
                    select={'ctime': "DATE_FORMAT({}.create_datetime,'%%Y-%%m-%%d')".format(model._meta.db_table)}). \
                    values('ctime').annotate(ct=Sum(field.get(model)[-1]))
                for item in queryset:
                    try:
                        date_dict[item['ctime']][1] = item['ct'] + date_dict[item['ctime']][1]
                    except Exception as e:
                        continue
            data_dict = {'name': name, 'data': list(date_dict.values())}
            return data_dict
        elif name == '攻击IP数量':
            for i in range(0, 30):
                date = today - timedelta(days=i)
                date_dict[date.strftime("%Y-%m-%d")] = [time.mktime(date.timetuple()) * 1000, 0]

            # 瑞数动态防御系统攻击IP统计
            botgate_queryset = models.BotgateAttackIp.objects.filter(create_datetime__gt=today - timedelta(days=29)). \
                extra(select={'ctime': "DATE_FORMAT(web_botgateattackip.create_datetime,'%%Y-%%m-%%d')"}). \
                values('ctime').annotate(ct=Count('src_ip'))

            for item in botgate_queryset:
                try:
                    date_dict[item['ctime']][1] = item['ct'] + date_dict[item['ctime']][1]
                except Exception as e:
                    continue

            # 天眼攻击IP统计
            skyeye_queryset = models.SkyEyeLog.objects.filter(create_datetime__gt=today - timedelta(days=29)).exclude(
                attack_sip=''). \
                extra(select={'ctime': "DATE_FORMAT(web_skyeyelog.create_datetime,'%%Y-%%m-%%d')"}). \
                values('ctime', 'attack_sip').annotate(ct=Count('attack_sip'))
            for item in skyeye_queryset:
                date_dict[item['ctime']][1] = date_dict[item['ctime']][1] + 1

            # 深信服攻击IP统计
            sangfor_fw_queryset = models.SangforFwAttackLog.objects.filter(
                create_datetime__gt=today - timedelta(days=29)). \
                extra(select={'ctime': "DATE_FORMAT(web_sangforfwattacklog.create_datetime,'%%Y-%%m-%%d')"}). \
                values('ctime', 'src_ip').annotate(ct=Count('src_ip'))

            for item in sangfor_fw_queryset:
                date_dict[item['ctime']][1] = date_dict[item['ctime']][1] + 1

            data_dict = {'name': name, 'data': list(date_dict.values())}
            return data_dict
    else:
        for i in range(0, 30):
            date = today - timedelta(days=i)
            date_dict[date.strftime("%Y-%m-%d")] = [time.mktime(date.timetuple()) * 1000, 0]
        queryset = model_list[0].objects.filter(create_datetime__gt=today - timedelta(days=29)).extra(
            select={
                'ctime': "DATE_FORMAT({}.create_datetime,'%%Y-%%m-%%d')".format(model_list[0]._meta.db_table)}). \
            values('ctime').annotate(ct=Sum(field[0]))
        for item in queryset:
            try:
                date_dict[item['ctime']][1] = item['ct']
            except Exception as e:
                continue
        data_dict = {'name': name, 'data': list(date_dict.values())}
        return data_dict


def home(request):
    today = datetime.datetime.now().date() + timedelta(days=1)
    date_dict = OrderedDict()
    for i in range(0, 10):
        date = today - timedelta(days=i)
        date_dict[date.strftime("%Y-%m-%d")] = {'atk_count': 0,
                                                'atkip_count': 0,
                                                'abnormal_request_count': 0,
                                                'attack_count': 0,
                                                'total': 0}
    k01_queryset = models.K01.objects.filter(create_datetime__gt=today - timedelta(days=9)).extra(
        select={
            'ctime': "DATE_FORMAT({}.create_datetime,'%%Y-%%m-%%d')".format(models.K01._meta.db_table)}). \
        values('ctime').annotate(ct=Sum('atk_count'))
    for item in k01_queryset:
        try:
            date_dict[item['ctime']]['atk_count'] = item['ct']
        except Exception as e:
            continue

    sanforfw_queryset = models.SangforFw.objects.filter(create_datetime__gt=today - timedelta(days=9)).extra(
        select={
            'ctime': "DATE_FORMAT({}.create_datetime,'%%Y-%%m-%%d')".format(models.SangforFw._meta.db_table)}). \
        values('ctime').annotate(ct=Sum('attack_count'))
    for item in sanforfw_queryset:
        try:
            date_dict[item['ctime']]['attack_count'] = item['ct']
        except Exception as e:
            continue

    skyeye_queryset = models.SkyEye.objects.filter(create_datetime__gt=today - timedelta(days=9)).extra(
        select={
            'ctime': "DATE_FORMAT({}.create_datetime,'%%Y-%%m-%%d')".format(models.SkyEye._meta.db_table)}). \
        values('ctime').annotate(ct=Sum('total'))
    for item in skyeye_queryset:
        try:
            date_dict[item['ctime']]['total'] = item['ct']
        except Exception as e:
            continue

    botgate_queryset = models.Botgate.objects.filter(create_datetime__gte=today - timedelta(days=9)).extra(
        select={
            'ctime': "DATE_FORMAT({}.create_datetime,'%%Y-%%m-%%d')".format(models.Botgate._meta.db_table)}). \
        values('ctime').annotate(ct=Sum('abnormal_request_count'))
    for item in botgate_queryset:
        date_dict[item['ctime']]['abnormal_request_count'] = item['ct']

    # 瑞数动态防御系统攻击IP统计
    botgate_attackip_queryset = models.BotgateAttackIp.objects.filter(create_datetime__gt=today - timedelta(days=29)). \
        extra(select={'ctime': "DATE_FORMAT(web_botgateattackip.create_datetime,'%%Y-%%m-%%d')"}). \
        values('ctime').annotate(ct=Count('src_ip'))
    for item in botgate_attackip_queryset:
        try:
            date_dict[item['ctime']]['atkip_count'] = item['ct'] + date_dict[item['ctime']]['atkip_count']
        except Exception as e:
            continue

    # 天眼攻击IP统计
    skyeye_attackip_queryset = models.SkyEyeLog.objects.filter(create_datetime__gt=today - timedelta(days=29)).exclude(
        attack_sip=''). \
        extra(select={'ctime': "DATE_FORMAT(web_skyeyelog.create_datetime,'%%Y-%%m-%%d')"}). \
        values('ctime', 'attack_sip').annotate(ct=Count('attack_sip'))
    for item in skyeye_attackip_queryset:
        try:
            date_dict[item['ctime']]['atkip_count'] = date_dict[item['ctime']]['atkip_count'] + 1
        except Exception as e:
            continue

    # 深信服攻击IP统计
    sangfor_fw_attackip_queryset = models.SangforFwAttackLog.objects.filter(
        create_datetime__gt=today - timedelta(days=29)). \
        extra(select={'ctime': "DATE_FORMAT(web_sangforfwattacklog.create_datetime,'%%Y-%%m-%%d')"}). \
        values('ctime', 'src_ip').annotate(ct=Count('src_ip'))

    for item in sangfor_fw_attackip_queryset:
        try:
            date_dict[item['ctime']]['atkip_count'] = date_dict[item['ctime']]['atkip_count'] + 1
        except Exception as e:
            continue

    data_list = []
    for k, v in date_dict.items():
        total_count = v.get('atk_count') + v.get('abnormal_request_count') + v.get('attack_count') + v.get('total')
        data_dcit = {'ctime': k, 'atk_count': "{:,}".format(v.get('atk_count')),
                     'abnormal_request_count': "{:,}".format(v.get('abnormal_request_count')),
                     'attack_count': "{:,}".format(v.get('attack_count')),
                     'total': "{:,}".format(v.get('total')),
                     'total_count': "{:,}".format(total_count),
                     'atkip_count': "{:,}".format(v.get('atkip_count'))
                     }
        data_list.append(data_dcit)

    current_datetime = datetime.datetime.now()
    current_time = current_datetime.time()
    specific_time_start = datetime.time(hour=15, minute=0, second=0, microsecond=0)
    specific_time_end = datetime.time(hour=17, minute=0, second=0, microsecond=0)
    is_day = False
    if current_time < specific_time_start:
        start_datetime_str = "%s %s" % ((current_datetime - timedelta(days=1)).strftime('%Y-%m-%d'), "15:00")
        start_datetime = datetime.datetime.strptime(start_datetime_str, '%Y-%m-%d %H:%M')
        current_date = current_datetime
        statistics_all_dict = statistics_all(current_date, data_list[1], is_day, start_datetime)
    elif current_time >= specific_time_start and current_time <= specific_time_end:
        is_day = True
        start_datetime_str = "%s %s" % ((current_datetime - timedelta(days=1)).strftime('%Y-%m-%d'), "15:00")
        start_datetime = datetime.datetime.strptime(start_datetime_str, '%Y-%m-%d %H:%M')
        current_date = current_datetime
        statistics_all_dict = statistics_all(current_date, data_list[1:3], is_day, start_datetime)
    else:
        start_datetime_str = "%s %s" % (current_datetime.strftime('%Y-%m-%d'), "15:00")
        start_datetime = datetime.datetime.strptime(start_datetime_str, '%Y-%m-%d %H:%M')
        current_date = current_datetime + datetime.timedelta(days=1)
        statistics_all_dict = statistics_all(current_date, data_list[0], is_day, start_datetime)

    return render(request, 'home.html', {'queryset': data_list, 'statistics_all_dict': statistics_all_dict})


def statistics_all(current_date, data_list, is_day, start_datetime=None):
    statistics_dict = {}
    if is_day:
        try:
            statistics_dict['total_count'] = data_list[0].get('total_count')
            current_total_count = int(data_list[0].get('total_count').replace(',', ''))
            yesterday_total_count = int(data_list[1].get('total_count').replace(',', ''))
            relative_yesterday_percentage = round(
                (current_total_count - yesterday_total_count) / yesterday_total_count * 100, 2)
            statistics_dict[
                'relative_yesterday'] = "上升<span class='highlight-text'>%s%%</span>，" % relative_yesterday_percentage if relative_yesterday_percentage > 0 else "下降<span class='highlight-text'>%s%%</span>，" % abs(
                relative_yesterday_percentage)
            statistics_dict['k01_atk_count'] = data_list[0].get('atk_count')
            statistics_dict['abnormal_request_count'] = data_list[0].get('abnormal_request_count')
            statistics_dict['sangfor_fw_attack_count'] = data_list[0].get('attack_count')
            statistics_dict['skyeye_attack_count'] = data_list[0].get('total')
            statistics_dict['atkip_count'] = data_list[0].get('atkip_count')

            statistics_dict['start_datetime'] = start_datetime
            statistics_dict['end_datetime'] = start_datetime + datetime.timedelta(days=1)
            blockip_queryset = models.BlockIp.objects.filter(create_datetime__year=current_date.year,
                                                             create_datetime__month=current_date.month,
                                                             create_datetime__day=current_date.day)
            statistics_dict['blockip_list'] = ','.join(
                ['{}({})'.format(item.src_ip, item.location) for item in blockip_queryset])

            statistics_dict['blockip_manual'] = blockip_queryset.filter(block_type=1).count()
            statistics_dict['blockip_automatic'] = blockip_queryset.filter(block_type=2).count()
            location_account = models.BlockIp.objects.filter(create_datetime__year=current_date.year,
                                                             create_datetime__month=current_date.month,
                                                             create_datetime__day=current_date.day). \
                                   values('location').annotate(ct=Count('src_ip')).order_by('-ct')[0:10]
            statistics_dict['botgate_location_account'] = ','.join(
                ["{}<span class='highlight-text'>{}</span>个".format(item['location'], item['ct']) for item in
                 location_account])

            botgate_website_request = models.BotgateWebSiteRequest.objects.filter(
                create_datetime__year=current_date.year,
                create_datetime__month=current_date.month,
                create_datetime__day=current_date.day,
                request_type=2
            ).values('website').annotate(
                ct=Sum('request_count')).order_by('-ct')[0:5]
            statistics_dict['botgate_website_request'] = ",".join([
                "{},<span class='highlight-text'>{:,}</span>次".format(item['website'], item['ct']) for item in
                botgate_website_request])
            botgate_injectattacktype_queryset = models.BotgateInjectAttackType.objects.filter(
                create_datetime__year=current_date.year,
                create_datetime__month=current_date.month,
                create_datetime__day=current_date.day). \
                                                    values('attack_type').annotate(ct=Sum('attack_count')).order_by(
                '-ct')[0:5]
            statistics_dict['injectattacktype'] = ",".join([
                "{},<span class='highlight-text'>{:,}</span>次".format(item['attack_type'], item['ct']) for item in
                botgate_injectattacktype_queryset])

            botgate_ndaytype_queryset = models.BotgateNdayType.objects.filter(create_datetime__year=current_date.year,
                                                                              create_datetime__month=current_date.month,
                                                                              create_datetime__day=current_date.day). \
                                            values('nday_name').annotate(ct=Sum('nday_attack_count')).order_by('-ct')[
                                        0:5]
            statistics_dict['ndayattack'] = ",".join(
                ["{},<span class='highlight-text'>{:,}</span>次".format(item['nday_name'], item['ct']) for item in
                 botgate_ndaytype_queryset])
            k01_obj = models.K01.objects.filter(create_datetime__year=current_date.year,
                                                create_datetime__month=current_date.month,
                                                create_datetime__day=current_date.day).first()

            statistics_dict['outgoing_count'] = k01_obj.outgoing_count
            k01_attackip_count = models.K01AttackIp.objects.filter(create_datetime__year=current_date.year,
                                                                   create_datetime__month=current_date.month,
                                                                   create_datetime__day=current_date.day). \
                values('sip').annotate(ct=Count('sip')).count()

            statistics_dict['k01_attackip_count'] = k01_attackip_count
            total_blockip_count = k01_attackip_count + statistics_dict['blockip_manual'] + \
                                  statistics_dict['blockip_automatic']
            statistics_dict['total_blockip_count'] = total_blockip_count
            last_day = current_date - timedelta(days=1)

            last_blockip_count = models.BlockIp.objects.filter(create_datetime__year=last_day.year,
                                                               create_datetime__month=last_day.month,
                                                               create_datetime__day=last_day.day).count()
            last_k01_attackip_count = models.K01AttackIp.objects.filter(create_datetime__year=last_day.year,
                                                                        create_datetime__month=last_day.month,
                                                                        create_datetime__day=last_day.day). \
                values('sip').annotate(ct=Count('sip')).count()
            last_total_blockip_count = last_blockip_count + last_k01_attackip_count
            relative_yesterday_blockip_percentage = round(
                (total_blockip_count - last_total_blockip_count) / last_total_blockip_count * 100, 2)
            statistics_dict[
                'relative_yesterday_blockip'] = "上升<span class='highlight-text'>%s%%</span>，" % relative_yesterday_blockip_percentage if relative_yesterday_blockip_percentage > 0 else "下降<span class='highlight-text'>%s%%</span>，" % abs(
                relative_yesterday_blockip_percentage)
        except Exception as ex:
            print(ex)
    else:
        try:
            statistics_dict['total_count'] = data_list.get('total_count')
            statistics_dict['k01_atk_count'] = data_list.get('atk_count')
            statistics_dict['abnormal_request_count'] = data_list.get('abnormal_request_count')
            statistics_dict['sangfor_fw_attack_count'] = data_list.get('attack_count')
            statistics_dict['skyeye_attack_count'] = data_list.get('total')
            statistics_dict['atkip_count'] = data_list.get('atkip_count')
            blockip_queryset = models.BlockIp.objects.filter(create_datetime__year=current_date.year,
                                                             create_datetime__month=current_date.month,
                                                             create_datetime__day=current_date.day)
            statistics_dict['blockip_list'] = ','.join(
                ['{}({})'.format(item.src_ip, item.location) for item in blockip_queryset])
            statistics_dict['blockip_manual'] = blockip_queryset.filter(block_type=1).count()
            statistics_dict['blockip_automatic'] = blockip_queryset.filter(block_type=2).count()

            location_account = models.BlockIp.objects.filter(create_datetime__year=current_date.year,
                                                             create_datetime__month=current_date.month,
                                                             create_datetime__day=current_date.day). \
                                   values('location').annotate(ct=Count('src_ip')).order_by('-ct')[0:10]
            statistics_dict['botgate_location_account'] = ','.join(
                ["{}<span class='highlight-text'>{}</span>个".format(item['location'], item['ct']) for item in
                 location_account])

            botgate_website_request = models.BotgateWebSiteRequest.objects.filter(
                create_datetime__year=current_date.year,
                create_datetime__month=current_date.month,
                create_datetime__day=current_date.day,
                request_type=2
            ).values('website').annotate(
                ct=Sum('request_count')).order_by('-ct')[0:5]
            statistics_dict['botgate_website_request'] = [{item['website']: "{:,}".format(item['ct'])} for
                                                          item in botgate_website_request]
            statistics_dict['statistics_datetime'] = current_date.strftime('%Y-%m-%d %H:%M:%S')
            statistics_dict['start_datetime'] = start_datetime
            statistics_dict['end_datetime'] = datetime.datetime.now()
            botgate_website_request = models.BotgateWebSiteRequest.objects.filter(
                create_datetime__year=current_date.year,
                create_datetime__month=current_date.month,
                create_datetime__day=current_date.day,
                request_type=2
            ).values('website').annotate(
                ct=Sum('request_count')).order_by('-ct')[0:5]
            statistics_dict['botgate_website_request'] = ",".join([
                "{},<span class='highlight-text'>{:,}</span>次".format(item['website'], item['ct']) for item in
                botgate_website_request])
            botgate_injectattacktype_queryset = models.BotgateInjectAttackType.objects.filter(
                create_datetime__year=current_date.year,
                create_datetime__month=current_date.month,
                create_datetime__day=current_date.day). \
                                                    values('attack_type').annotate(ct=Sum('attack_count')).order_by(
                '-ct')[0:5]
            statistics_dict['injectattacktype'] = ",".join([
                "{},<span class='highlight-text'>{:,}</span>次".format(item['attack_type'], item['ct']) for item in
                botgate_injectattacktype_queryset])

            botgate_ndaytype_queryset = models.BotgateNdayType.objects.filter(create_datetime__year=current_date.year,
                                                                              create_datetime__month=current_date.month,
                                                                              create_datetime__day=current_date.day). \
                                            values('nday_name').annotate(ct=Sum('nday_attack_count')).order_by('-ct')[
                                        0:5]
            statistics_dict['ndayattack'] = ",".join(
                ["{},<span class='highlight-text'>{:,}</span>次".format(item['nday_name'], item['ct']) for item in
                 botgate_ndaytype_queryset])
            k01_obj = models.K01.objects.filter(create_datetime__year=current_date.year,
                                                create_datetime__month=current_date.month,
                                                create_datetime__day=current_date.day).first()
            statistics_dict['outgoing_count'] = k01_obj.outgoing_count
            k01_attackip_count = models.K01AttackIp.objects.filter(create_datetime__year=current_date.year,
                                                                   create_datetime__month=current_date.month,
                                                                   create_datetime__day=current_date.day). \
                values('sip').annotate(ct=Count('sip')).count()
            statistics_dict['k01_attackip_count'] = k01_attackip_count
        except Exception as ex:
            print(ex)
    statistics_dict['is_day'] = is_day
    return statistics_dict


def home_chart(request):
    account_mapping = [
        {'model': [models.Botgate, models.K01], 'name': '攻击合计',
         'field': {models.Botgate: ['abnormal_request_count'], models.K01: ['atk_count']}},
        {'model': [models.BotgateAttackIp, models.SkyEyeLog, models.SangforFwAttackLog], 'name': '攻击IP数量',
         'field': ['attack_ip']},
        {'model': [models.K01], 'name': '威胁情报联防阻断系统(k01)', 'field': ['atk_count']},
        {'model': [models.Botgate], 'name': '瑞数动态防御系统', 'field': ['abnormal_request_count']},
        {'model': [models.SangforFw], 'name': '深信服防火墙', 'field': ['attack_count']},
        {'model': [models.SkyEye], 'name': '天眼分析平台', 'field': ['total']},
    ]
    data_list = []
    for item in account_mapping:
        data_list.append(get_data_dict(item['model'], item['name'], item.get('field', '')))
    return JsonResponse({'status': True, 'data': data_list})
